﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace FreeDream.Utils
{
    /// <summary>
    /// 推荐使用，性能高
    /// 1.HttpClient 需要单例模型 
    /// </summary>
    public class HttpHelper
    {
        //HttpClient 推荐的做法就是在应用程序生命周期内初始化一次，除非你有特殊的理由不这么做
        private static readonly HttpClient client = new HttpClient();

        #region 单例模型

        private static readonly object LockObj = new object();

        //private  HttpClient client;

        //public  HttpClient GetInstance()
        //{
        //    if (client == null)
        //    {
        //        lock (LockObj)
        //        {
        //            if (client == null)
        //            {
        //                client = new HttpClient();
        //            }
        //        }
        //    }
        //    return client;
        //}

        #endregion

        #region 1. 不带类型的GET和POST
        /// <summary>
        /// 发起POST同步请求-json参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData">var data = new { start = start, end = end, orderby = orderby, condition = condition }.toJson</param>
        /// <param name="timeOut">设置超时时间(秒)</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static string Post(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            postData = postData ?? "";
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            //using (HttpClient client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(timeOut);
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
                {
                    if (contentTypeDescription != null)
                        httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentTypeDescription);

                    HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
                    var res = response.Content.ReadAsStringAsync().Result;
                    return res;
                }
            }
        }
        /// <summary>
        /// 发起POST同步请求-普通参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="timeOut">设置超时时间(秒)</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static string PostForm(string url, Dictionary<string, string> postData, int timeOut = 40, ContentType contentType = ContentType.UrlEncoded, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            //using (HttpClient client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(timeOut);
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }

                using (HttpContent httpContent = new FormUrlEncodedContent(postData))
                {
                    //if (contentTypeDescription != null)
                    //    httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentTypeDescription);

                    HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
                    var res = response.Content.ReadAsStringAsync().Result;
                    return res;
                }
            }
        }
        /// <summary>
        /// 发起POST同步请求-普通参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="timeOut">设置超时时间(秒)</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static async Task<string> PostFormAsync(string url, Dictionary<string, string> postData, int timeOut = 40, ContentType contentType = ContentType.UrlEncoded, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            //using (HttpClient client = new HttpClient())
            {
                //client.Timeout = TimeSpan.FromSeconds(timeOut);
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }

                using (HttpContent httpContent = new FormUrlEncodedContent(postData))
                {
                    HttpResponseMessage response = await client.PostAsync(url, httpContent);
                    return await response.Content.ReadAsStringAsync();
                }
            }
        }
        /// <summary>
        /// 发起POST异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static async Task<string> HttpPostAsync(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            postData = postData ?? "";
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            //using (HttpClient client = new HttpClient())
            {
                client.Timeout = new TimeSpan(0, 0, timeOut);
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
                {
                    if (contentTypeDescription != null)
                        httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentTypeDescription);

                    HttpResponseMessage response = await client.PostAsync(url, httpContent);
                    return await response.Content.ReadAsStringAsync();
                }
            }
        }

        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static string Get(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            //using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (contentTypeDescription != null)
                {
                    client.DefaultRequestHeaders.Add("ContentType", contentTypeDescription);
                }
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                HttpResponseMessage response = client.GetAsync(url).Result;
                return response.Content.ReadAsStringAsync().Result;
            }
        }
        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static string Delete(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            //using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (contentTypeDescription != null)
                {
                    client.DefaultRequestHeaders.Add("ContentType", contentTypeDescription);
                }
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                HttpResponseMessage response = client.DeleteAsync(url).Result;
                return response.Content.ReadAsStringAsync().Result;
            }
        }

        /// <summary>
        /// 发起GET异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static async Task<string> HttpGetAsync(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            //using (HttpClient client = new HttpClient())
            {
                if (contentTypeDescription != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    client.DefaultRequestHeaders.Add("ContentType", contentTypeDescription);
                }
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                }
                HttpResponseMessage response = await client.GetAsync(url);
                return await response.Content.ReadAsStringAsync();
            }
        }
        #endregion

        #region 2.0 带类型的POST和GET

        /// <summary>
        /// 发起POST同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="timeOut">超时时间，单位是秒</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static T Post<T>(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = Post(url, postData, timeOut, contentType, headers);
            try
            {
                return res.ToEntity<T>();
            }
            catch (Exception e)
            {
                QueenLogger.Error("接口返回数据反序列化失败:" + res, "HttpToEntityError", e);
                //throw new Exception("接口返回数据反序列化失败");
            }
            return default(T);
        }
        /// <summary>
        /// 发起POST同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData">var values = new Dictionary<string, string>{{ "thing1", "hello" },{ "thing2", "world" }};</param>
        /// <param name="timeOut">超时时间，单位是秒</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static T PostForm<T>(string url, Dictionary<string, string> postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = PostForm(url, postData, timeOut, contentType, headers);
            try
            {
                return res.ToEntity<T>();
            }
            catch (Exception e)
            {
                QueenLogger.Error("接口返回数据反序列化失败:" + res, "HttpToEntityError", e);
                //throw new Exception("接口返回数据反序列化失败");
            }
            return default(T);
        }
        /// <summary>
        /// 发起POST异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData">var values = new Dictionary<string, string>{{ "thing1", "hello" },{ "thing2", "world" }};</param>
        /// <param name="timeOut">超时时间，单位是秒</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static async Task<T> PostFormAsync<T>(string url, Dictionary<string, string> postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = await PostFormAsync(url, postData, timeOut, contentType, headers);
            try
            {
                return res.ToEntity<T>();
            }
            catch (Exception e)
            {
                QueenLogger.Error("接口返回数据反序列化失败:" + res, "HttpToEntityError", e);
                //throw new Exception("接口返回数据反序列化失败");
            }
            return default(T);
        }

        /// <summary>
        /// 发起POST异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static async Task<T> HttpPostAsync<T>(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = await HttpPostAsync(url, postData, timeOut, contentType, headers);
            return res.ToEntity<T>();
        }

        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static T Get<T>(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            return Get(url, contentType, headers).ToEntity<T>();
        }

        /// <summary>
        /// 发起GET异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static async Task<T> HttpGetAsync<T>(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = await HttpGetAsync(url, contentType, headers);
            return res.ToEntity<T>();
        }
        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static T Delete<T>(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            return Delete(url, contentType, headers).ToEntity<T>();
        }

        #endregion

        #region 3.0 POST FORM DATA

        /// <summary>
        /// 测试成功，可以上传文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postParameters"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static string PostFile(string url, Dictionary<string, object> postParameters, Dictionary<string, string> headers = null)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                var content = new MultipartFormDataContent();
                foreach (var param in postParameters)
                {
                    if (param.Value is FileParameter)
                    {
                        //添加文件参数
                        FileParameter fileToUpload = (FileParameter)param.Value;
                        content.Add(new ByteArrayContent(fileToUpload.File), param.Key, fileToUpload.FileName);
                    }
                    else
                    {
                        //添加字符串参数
                        content.Add(new StringContent(param.Value.ToString()), param.Key);
                    }
                }
                var result = client.PostAsync(url, content).Result.Content.ReadAsStringAsync().Result;
                return result;
            }
        }
        /// <summary>
        /// 异步上传文件，可以用
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postParameters"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static async Task<string> PostFileAsync(string url, Dictionary<string, object> postParameters, Dictionary<string, string> headers = null)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                var content = new MultipartFormDataContent();
                foreach (var param in postParameters)
                {
                    if (param.Value is FileParameter)
                    {
                        //添加文件参数
                        FileParameter fileToUpload = (FileParameter)param.Value;
                        content.Add(new ByteArrayContent(fileToUpload.File), param.Key, fileToUpload.FileName);
                    }
                    else
                    {
                        //添加字符串参数
                        content.Add(new StringContent(param.Value.ToString()), param.Key);
                    }
                }
                var result = await client.PostAsync(url, content).Result.Content.ReadAsStringAsync();
                return result;
            }
        }
        /// <summary>
        /// 请求并接收文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postParameters"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static byte[] PostAndGetFile(string url, Dictionary<string, object> postParameters, Dictionary<string, string> headers = null)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                var content = new MultipartFormDataContent();
                foreach (var param in postParameters)
                {
                    if (param.Value is FileParameter)
                    {
                        //添加文件参数
                        FileParameter fileToUpload = (FileParameter)param.Value;
                        content.Add(new ByteArrayContent(fileToUpload.File), param.Key, fileToUpload.FileName);
                    }
                    else
                    {
                        //添加字符串参数
                        content.Add(new StringContent(param.Value.ToString()), param.Key);
                    }
                }
                var result = client.PostAsync(url, content).Result.Content.ReadAsByteArrayAsync().Result;
                return result;
            }
        }


        public static T PostFile<T>(string url, Dictionary<string, object> postParameters)
        {
            var res = PostFile(url, postParameters);
            try
            {
                return res.ToEntity<T>();
            }
            catch (Exception e)
            {
                QueenLogger.Error("接口返回数据反序列化失败:" + res, "HttpToEntityError", e);
                throw new Exception("接口返回数据反序列化失败");
            }
        }


        #endregion

        #region 4.0 上传和下载文件

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="serverFileName">服务器上文件名 如 close.png</param>
        /// <param name="localFileName">要保存到本地的路径全名 如：C://Download/close.png</param>
        /// <returns></returns>
        public static bool DownLoad(string uri, string localFileName)
        {
            var server = new Uri(uri);
            var p = Path.GetDirectoryName(localFileName);
            if (!Directory.Exists(p)) Directory.CreateDirectory(p);

            // 发起请求并异步等待结果
            //var httpClient = new HttpClient();
            var responseMessage = client.GetAsync(server).Result;
            if (responseMessage?.IsSuccessStatusCode ?? false)
            {
                using (var fs = File.Create(localFileName))
                {
                    // 获取结果，并转成 stream 保存到本地。
                    var streamFromService = responseMessage.Content.ReadAsStreamAsync().Result;
                    streamFromService.CopyTo(fs);
                    return true;
                }
            }
            else
                return false;
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="serverFileName">服务器上文件名 如 close.png</param>
        /// <param name="localFileName">要保存到本地的路径全名 如：C://Download/close.png</param>
        /// <returns></returns>
        public static async Task<bool> PostAndDownLoad(string uri, string postData, string localFileName)
        {
            //var server = new Uri(uri);
            try
            {
                var p = Path.GetDirectoryName(localFileName);
                if (!Directory.Exists(p)) Directory.CreateDirectory(p);

                // 发起请求并异步等待结果 
                using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
                {
                    string contentTypeDescription = EnumHelper.GetEnumDescription(ContentType.Json);
                    httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentTypeDescription);

                    HttpResponseMessage responseMessage = await client.PostAsync(uri, httpContent);
                    if (responseMessage.IsSuccessStatusCode)
                    {
                        using (var fs = File.Create(localFileName))
                        {
                            // 获取结果，并转成 stream 保存到本地。
                            var streamFromService = responseMessage.Content.ReadAsStreamAsync().Result;
                            streamFromService.CopyTo(fs);
                            return true;
                        }
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                var ss = ex.Message;
                return false;
            }

            //var responseMessage = client.GetAsync(server).Result;

        }

        /// <summary>
        /// 通过webapi上传单张图片文件
        /// </summary>
        /// <param name="uploadUri">上传路径</param>
        /// <param name="FullFileNames">图片文件的字节编码</param>
        /// <param name="FileStars">上传文件的保存路径前缀，可null，null则不分文件夹保存</param>
        /// <param name="FileNames">上传文件的保存名称</param>
        /// <returns></returns>
        public static List<UploadFile> UploadImageFiles(string uploadUri, byte[] FullFile, string FileStars, string FileNames)
        {
            // 判断传入参数是否正确
            if (string.IsNullOrEmpty(uploadUri) || FullFile == null || FileNames == null)
            {
                //WriteLog("上传文件时传入参数异常");
                return null;
            }
            // 上传服务uri
            var clineturi = new Uri(uploadUri);

            //using (var client = new HttpClient())
            {
                client.Timeout = new TimeSpan(0, 0, 0, 30, 30);
                // 以MultipartFormData格式上传
                using (var content = new MultipartFormDataContent())
                {
                    // 文件往content添加一条ByteArrayContent
                    // 发送二进制内容
                    var fileContent = new ByteArrayContent(FullFile);
                    // 设置上传后保存的前缀路径和文件名称(文件名称如果重复会特殊处理)
                    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                    if (FileStars != null) fileContent.Headers.ContentDisposition.FileNameStar = FileStars;
                    fileContent.Headers.ContentDisposition.FileName = FileNames;
                    content.Add(fileContent);
                    try
                    {
                        // 上传文件,获取返回的字符串内容
                        var result = client.PostAsync(clineturi, content).Result.Content.ReadAsStringAsync().Result;
                        return Newtonsoft.Json.JsonConvert.DeserializeObject<List<UploadFile>>(result);
                    }
                    catch (Exception ex)
                    {
                        //WriteLog(string.Format("上传文件出错！uri={0},FullFileNames={1}", uploadUri, FileStars.ToString()), ex);
                        return null;
                    }
                }
            }
        }

        #endregion

    }
    /// <summary>
    /// 文件参数模型
    /// </summary>
    public class FileParameter
    {
        /// <summary>
        /// 二进制的文件
        /// </summary>
        public byte[] File { get; set; }
        /// <summary>
        /// 文件名称,带拓展名
        /// </summary>
        public string FileName { get; set; }
        public string ContentType { get; set; }

        #region 构造函数
        public FileParameter(byte[] file) : this(file, null) { }
        public FileParameter(byte[] file, string filename) : this(file, filename, null) { }
        public FileParameter(byte[] file, string filename, string contenttype)
        {
            File = file;
            FileName = filename;
            ContentType = contenttype;
        }
        #endregion

    }
    /// <summary>
    /// POST的ContentType枚举变量
    /// application/xml、application/json、application/text、application/x-www-form-urlencoded
    /// </summary>
    public enum ContentType
    {
        [Description("application/x-www-form-urlencoded")]
        UrlEncoded = 1,

        [Description("application/json")]
        Json = 2,

        [Description("multipart/form-data")]
        FormData = 3,

        [Description("multipart/xml")]
        Xml = 4,

        [Description("multipart/text")]
        Text = 5,
    }

    public class UploadFile
    {
        public string FileName { get; set; }
        public string FilePath { get; set; }
    }


    /// <summary>
    /// 适配coer版本的数据库访问
    /// </summary>
    public class HttpHelperExt
    {
        #region 1. 不带类型的GET和POST
        /// <summary>
        /// 发起POST同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData">var data = new { start = start, end = end, orderby = orderby, condition = condition }.toJson</param>
        /// <param name="timeOut">设置超时时间(秒)</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static string Post(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            postData = postData ?? "";
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            using (HttpClient client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(timeOut);
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
                {
                    if (contentTypeDescription != null)
                        httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentTypeDescription);

                    HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
                    if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        return new { Code = 417, Message = "登陆过期" }.ToJson();

                    }
                    var result = response.Content.ReadAsStringAsync().Result;
                    if (response.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        return result;
                    }
                    var resModel = new { Code = (int)response.StatusCode, Message = response.RequestMessage.RequestUri, Data = result };
                    return resModel.ToJson();
                }
            }
        }


        /// <summary>
        /// 发起POST异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static async Task<string> HttpPostAsync(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            postData = postData ?? "";
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            using (HttpClient client = new HttpClient())
            {
                client.Timeout = new TimeSpan(0, 0, timeOut);
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
                {
                    if (contentTypeDescription != null)
                        httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentTypeDescription);

                    HttpResponseMessage response = await client.PostAsync(url, httpContent);
                    if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        return new { Code = 417, Message = "登陆过期" }.ToJson();

                    }
                    var result = response.Content.ReadAsStringAsync().Result;
                    if (response.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        return result;
                    }
                    return new { Code = response.StatusCode.ToString(), Message = response.RequestMessage, Data = result }.ToJson();
                }
            }
        }

        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static string Get(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (contentTypeDescription != null)
                {
                    client.DefaultRequestHeaders.Add("ContentType", contentTypeDescription);
                }
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                HttpResponseMessage response = client.GetAsync(url).Result;
                if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    return new { Code = 417, Message = "登陆过期" }.ToJson();

                }
                var result = response.Content.ReadAsStringAsync().Result;
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    return result;
                }
                return new { Code = response.StatusCode.ToString(), Message = response.RequestMessage, Data = result }.ToJson();
            }
        }
        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static string Delete(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (contentTypeDescription != null)
                {
                    client.DefaultRequestHeaders.Add("ContentType", contentTypeDescription);
                }
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                HttpResponseMessage response = client.DeleteAsync(url).Result;
                return response.Content.ReadAsStringAsync().Result;
            }
        }

        /// <summary>
        /// 发起GET异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static async Task<string> HttpGetAsync(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            string contentTypeDescription = EnumHelper.GetEnumDescription(contentType);
            using (HttpClient client = new HttpClient())
            {
                if (contentTypeDescription != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    client.DefaultRequestHeaders.Add("ContentType", contentTypeDescription);
                }
                if (headers != null)
                {
                    client.DefaultRequestHeaders.Clear();
                    foreach (var header in headers)
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                }
                HttpResponseMessage response = await client.GetAsync(url);
                return await response.Content.ReadAsStringAsync();
            }
        }
        #endregion

        #region 2.0 带类型的POST和GET

        /// <summary>
        /// 发起POST同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="timeOut">超时时间，单位是秒</param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static T Post<T>(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = Post(url, postData, timeOut, contentType, headers);
            try
            {
                return res.ToEntity<T>();
            }
            catch (Exception e)
            {
                QueenLogger.Error("接口返回数据反序列化失败:" + res, "HttpToEntityError", e);
                //throw new Exception("接口返回数据反序列化失败");
            }
            return default(T);
        }


        /// <summary>
        /// 发起POST异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
        /// <param name="headers">填充消息头</param>        
        /// <returns></returns>
        public static async Task<T> HttpPostAsync<T>(string url, string postData = null, int timeOut = 30, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = await HttpPostAsync(url, postData, timeOut, contentType, headers);
            return res.ToEntity<T>();
        }

        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static T Get<T>(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            return Get(url, contentType, headers).ToEntity<T>();
        }

        /// <summary>
        /// 发起GET异步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static async Task<T> HttpGetAsync<T>(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            var res = await HttpGetAsync(url, contentType, headers);
            return res.ToEntity<T>();
        }
        /// <summary>
        /// 发起GET同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static T Delete<T>(string url, ContentType contentType = ContentType.Json, Dictionary<string, string> headers = null)
        {
            return Delete(url, contentType, headers).ToEntity<T>();
        }

        #endregion

        #region 3.0 POST FORM DATA

        /// <summary>
        /// 测试成功，可以上传文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postParameters"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static string PostFile(string url, Dictionary<string, object> postParameters, Dictionary<string, string> headers = null)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                var content = new MultipartFormDataContent();
                foreach (var param in postParameters)
                {
                    if (param.Value is FileParameter)
                    {
                        //添加文件参数
                        FileParameter fileToUpload = (FileParameter)param.Value;
                        content.Add(new ByteArrayContent(fileToUpload.File), param.Key, fileToUpload.FileName);
                    }
                    else
                    {
                        //添加字符串参数
                        content.Add(new StringContent(param.Value.ToString()), param.Key);
                    }
                }
                var result = client.PostAsync(url, content).Result.Content.ReadAsStringAsync().Result;
                return result;
            }
        }
        /// <summary>
        /// 异步上传文件，可以用
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postParameters"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static async Task<string> PostFileAsy(string url, Dictionary<string, object> postParameters, Dictionary<string, string> headers = null)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                var content = new MultipartFormDataContent();
                foreach (var param in postParameters)
                {
                    if (param.Value is FileParameter)
                    {
                        //添加文件参数
                        FileParameter fileToUpload = (FileParameter)param.Value;
                        content.Add(new ByteArrayContent(fileToUpload.File), param.Key, fileToUpload.FileName);
                    }
                    else
                    {
                        //添加字符串参数
                        content.Add(new StringContent(param.Value.ToString()), param.Key);
                    }
                }
                var result = await client.PostAsync(url, content).Result.Content.ReadAsStringAsync();
                return result;
            }
        }
        /// <summary>
        /// 请求并接收文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postParameters"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static byte[] PostAndGetFile(string url, Dictionary<string, object> postParameters, Dictionary<string, string> headers = null)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (!client.DefaultRequestHeaders.Contains(header.Key))
                        {
                            client.DefaultRequestHeaders.Add(header.Key, header.Value);
                        }
                    }
                }
                var content = new MultipartFormDataContent();
                foreach (var param in postParameters)
                {
                    if (param.Value is FileParameter)
                    {
                        //添加文件参数
                        FileParameter fileToUpload = (FileParameter)param.Value;
                        content.Add(new ByteArrayContent(fileToUpload.File), param.Key, fileToUpload.FileName);
                    }
                    else
                    {
                        //添加字符串参数
                        content.Add(new StringContent(param.Value.ToString()), param.Key);
                    }
                }
                var result = client.PostAsync(url, content).Result.Content.ReadAsByteArrayAsync().Result;
                return result;
            }
        }


        public static T PostFile<T>(string url, Dictionary<string, object> postParameters)
        {
            var res = PostFile(url, postParameters);
            try
            {
                return res.ToEntity<T>();
            }
            catch (Exception e)
            {
                QueenLogger.Error("接口返回数据反序列化失败:" + res, "HttpToEntityError", e);
                throw new Exception("接口返回数据反序列化失败");
            }
        }


        #endregion
    }

}
